{ "success": true, "task_id": "f45388a9-4169-41d4-aec8-fb8259c48d36", "trace_id": "1df9f664-fd74-476b-8038-b0b5f62ddf87", "data": [ { "id": "02702b40-272d-4838-8644-675105930658", "title": "Vibe", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/e850008a-d9a1-4c8f-acbd-a37f228946bc/image/02702b40-272d-4838-8644-675105930658.jpg", "lyric": "[Intro]\nYeah, yeah\nKeep talking, keep talking\nI love the way you sound\n[Verse 1]\nYour voice is like a drug I can't put down\nEvery word you say just pulls me in\nI'm addicted to the way you laugh out loud\nAnd how you whisper when the room goes dim\nTell me 'bout your day, tell me 'bout your fears\nI could listen to you talk for years\n[Pre-Chorus]\nDon't stop now, don't you dare\nI need your voice filling up the air\n[Chorus]\nKeep talking, keep talking to me\nYour words are all I fucking need\nKeep talking, keep talking, I'm high\nOff every sound you make tonight\nKeep talking\n[Verse 2]\nYou could read the phone book, I don't care\nJust the rhythm of your breathing's enough\nWhen you say my name, it's like a prayer\nAnd your silence hits me twice as rough\nEvery conversation feels like home\nNever want to hear this dial tone\n[Pre-Chorus]\nDon't stop now, don't you dare\nI need your voice filling up the air\n[Chorus]\nKeep talking, keep talking to me\nYour words are all I fucking need\nKeep talking, keep talking, I'm high\nOff every sound you make tonight\nKeep talking\n[Bridge]\nWhen the world gets loud and crazy\nYour voice cuts through the noise\nYou're my favorite conversation\nYou're my drug of choice\nKeep talking, keep talking\nKeep talking, keep talking\nKeep talking, keep talking\nKeep talking, keep talking\n[Chorus]\nKeep talking, keep talking to me\nYour words are all I fucking need\nKeep talking, keep talking, I'm high\nOff every sound you make tonight\nKeep talking\n[Outro]\nYeah, yeah\nKeep talking, keep talking\nNever stop that sound", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/e850008a-d9a1-4c8f-acbd-a37f228946bc/audio/02702b40-272d-4838-8644-675105930658.m4a", "video_url": null, "created_at": "2025-06-18T15:47:54.705246Z", "model": "FUZZ-1.0", "lyrics_timestamped": { "words": [ { "text": "[Intro]", "start": 0.64, "end": 0.64, "line_index": 0, "index_range": null, "wav2vec2_format": null }, ... { "text": "sound", "start": 179.84, "end": 180.48, "line_index": 63, "index_range": null, "wav2vec2_format": null } ] }, "state": "succeeded", "style": "Pop, upbeat tempo, modern production", "duration": 181.12 }, { "id": "be3fe757-621e-4017-9056-20aa7f01919e", "title": "Revive", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/e850008a-d9a1-4c8f-acbd-a37f228946bc/image/be3fe757-621e-4017-9056-20aa7f01919e.jpg", "lyric": "[Verse 1]\nI'm walking through the motions, moving day by day\nColors seem a little faded, nothing much to say\nFriends keep calling, asking if I'm doing fine\nBut I just smile and tell them everything's divine\n[Pre-Chorus]\nSomething's missing, can't quite name it\nFeels like I'm just going through the stages\n[Chorus]\nI'm barely breathing, barely feeling\nLike I'm floating through a life that isn't mine\nBarely breathing, barely healing\nSearching for a reason, searching for a sign\nTo feel alive again\nTo feel alive again\n[Verse 2]\nMorning coffee tastes like water, sunrise looks like rain\nEveryone around me laughs but I can't feel the same\nUsed to dance in silly moments, used to sing out loud\nNow I'm standing in the silence of a faceless crowd\n[Pre-Chorus]\nSomething's shifting, can't ignore it\nMaybe it's time to break these patterns\n[Chorus]\nI'm barely breathing, barely feeling\nLike I'm floating through a life that isn't mine\nBarely breathing, barely healing\nSearching for a reason, searching for a sign\nTo feel alive again\nTo feel alive again\n[Bridge]\nBut there's a beating in my chest\nA whisper saying \"don't give up yet\"\nMaybe tomorrow I'll remember\nHow to laugh and how to let\nMy heart wake up from this long sleep\nFind the fire I used to keep\n[Chorus]\nI'm barely breathing, barely feeling\nLike I'm floating through a life that isn't mine\nBarely breathing, barely healing\nSearching for a reason, searching for a sign\nTo feel alive again\nTo feel alive again\n[Outro]\nI'm gonna feel alive again\nI'm gonna feel alive again", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/e850008a-d9a1-4c8f-acbd-a37f228946bc/audio/be3fe757-621e-4017-9056-20aa7f01919e.m4a", "video_url": null, "created_at": "2025-06-18T15:48:01.139081Z", "model": "FUZZ-1.0", "lyrics_timestamped": { "words": [ { "text": "[Verse", "start": 0.64, "end": 0.64, "line_index": 0, "index_range": null, "wav2vec2_format": null }, ... { "text": "again", "start": 202.88, "end": 211.84, "line_index": 54, "index_range": null, "wav2vec2_format": null } ] }, "state": "succeeded", "style": "Pop, upbeat tempo, clean production, emotional vocals", "duration": 211.84 } ] }
返回結果一共有多個字段,介紹如下:
success,此時音樂生成任務的狀態情況。
data,此次音樂任務的結果 - id,此時音樂生成任務的 ID。
prompt,此時音樂生成任務的提示詞。
audio_url,此時音樂生成任務的音頻鏈接。
image_url,此時音樂生成任務的封面鏈接。
state,此時音樂生成任務的狀態。
duration,此時音樂的時長信息。
style,此時音樂的風格信息。
model,此時音樂生成任務采用的模型信息。
lyric,此時音樂生成任務的歌詞信息。
可以看到我們得到了想生成的音樂信息,我們只需要根據結果中 data 的音樂鏈接地址獲取生成的 Riffusion 音樂即可。
另外如果想生成對應的對接代碼,可以直接復制生成,例如 CURL 的代碼如下:
1 2 3 4 5 6 7 8 9
curl -X POST 'https://api.acedata.cloud/riffusion/audios' \ -H 'accept: application/json' \ -H 'authorization: Bearer {token}' \ -H 'content-type: application/json' \ -d '{ "model": "FUZZ-1.0", "action": "generate", "prompt": "A song for Christmas" }'
自定義生成
如果想自定義生成歌詞,可以輸入歌詞:
這時候 lyric 字段可以傳入類似如下內容:
1
[Verse]Woke up withthe sun inmy eyesNo clouds above just blue inthe skiesShoes onmy feet I’m ready to runEvery step feels like a loaded gun[Chorus]Happy days are rolling inLet the joy beneathmy skinNo more shadows no more liesJust the truth that lifts me high[Verse 2]Dancing throughthe city streetsA rhythm pounding inmy heartbeatStrangers smile it’s catching onThis world’s a stage we’re all a song[Chorus]Happy days are rolling inLet the joy beneathmy skinNo more shadows no more liesJust the truth that lifts me high[Bridge]Throw your worries out the doorLet them sink tothe ocean floorWe’re alive andit’s enoughLife is messy butit’s love[Chorus]Happy days are rolling inLet the joy beneathmy skinNo more shadows no more liesJust the truth that lifts me high
curl -X POST 'https://api.acedata.cloud/riffusion/audios' \ -H 'accept: application/json' \ -H 'authorization: Bearer {token}' \ -H 'content-type: application/json' \ -d '{ "model": "FUZZ-1.0", "action": "generate", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "custom": true }'
{ "success": true, "task_id": "978c2912-6a90-4048-b4c1-43f9cf18c28d", "trace_id": "08dfbb99-43ce-4f65-8fd1-74b98f2b121a", "data": [ { "id": "eac9ab69-e210-490b-9f8d-095a6f074f40", "title": "VibeRise", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/3f3e1354-52ad-4f5b-902c-5f83abd17def/image/eac9ab69-e210-490b-9f8d-095a6f074f40.jpg", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/3f3e1354-52ad-4f5b-902c-5f83abd17def/audio/eac9ab69-e210-490b-9f8d-095a6f074f40.m4a", "video_url": null, "created_at": "2025-06-23T01:57:33.438644Z", "model": "FUZZ-1.0", "lyrics_timestamped": { "words": [ { "end": 0.64, "index_range": null, "line_index": 0, "start": 0.64, "text": "[Verse]", "wav2vec2_format": null }, { "end": 0.64, "index_range": null, "line_index": 1, "start": 0.64, "text": "Woke", "wav2vec2_format": null }, ... ] }, "state": "succeeded", "style": "funk vibes, raspy, raw vocal texture", "duration": 158.08 }, { "id": "64fffe1f-b1aa-46dc-8012-b80ba319cf35", "title": "Pure Dawn", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/3f3e1354-52ad-4f5b-902c-5f83abd17def/image/64fffe1f-b1aa-46dc-8012-b80ba319cf35.jpg", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/3f3e1354-52ad-4f5b-902c-5f83abd17def/audio/64fffe1f-b1aa-46dc-8012-b80ba319cf35.m4a", "video_url": null, "created_at": "2025-06-23T01:57:33.963497Z", "model": "FUZZ-1.0", "lyrics_timestamped": { "words": [ { "end": 0.64, "index_range": null, "line_index": 0, "start": 0.64, "text": "[Verse]", "wav2vec2_format": null }, { "end": 0.64, "index_range": null, "line_index": 1, "start": 0.64, "text": "Woke", "wav2vec2_format": null }, ... ] }, "state": "succeeded", "style": "contemporary country", "duration": 175.36 } ] }
curl -X POST 'https://api.acedata.cloud/riffusion/audios' \ -H 'accept: application/json' \ -H 'authorization: Bearer {token}' \ -H 'content-type: application/json' \ -d '{ "action": "cover", "model": "FUZZ-1.0 Pro", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_id": "b7376272-3902-49b4-a83b-62f7e6ab505c" }'
{ "success": true, "task_id": "fe02997d-f58e-4886-9aa3-4074c9a430eb", "trace_id": "997bde4c-6063-4fc2-9b03-d837f1efc72d", "data": [ { "id": "be254182-d4b7-42b3-9ee2-b86db086cff1", "title": "Sunny Rise", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/c2f707a9-017d-4354-8bfa-436266dadbf6/image/be254182-d4b7-42b3-9ee2-b86db086cff1.jpg", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/c2f707a9-017d-4354-8bfa-436266dadbf6/audio/be254182-d4b7-42b3-9ee2-b86db086cff1.m4a", "video_url": null, "created_at": "2025-06-23T01:59:17.666629Z", "model": null, "lyrics_timestamped": { "words": [ { "end": 0.64, "index_range": null, "line_index": 0, "start": 0.64, "text": "[Verse]", "wav2vec2_format": null }, ... { "end": 237.44, "index_range": null, "line_index": 29, "start": 236.8, "text": "high", "wav2vec2_format": null } ] }, "state": "succeeded", "style": "", "duration": 239.46235827664398 }, { "id": "9b9d2810-eb2b-44d3-85c0-cb259afa13c3", "title": "Uplift", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/c2f707a9-017d-4354-8bfa-436266dadbf6/image/9b9d2810-eb2b-44d3-85c0-cb259afa13c3.jpg", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/c2f707a9-017d-4354-8bfa-436266dadbf6/audio/9b9d2810-eb2b-44d3-85c0-cb259afa13c3.m4a", "video_url": null, "created_at": "2025-06-23T01:59:23.065712Z", "model": null, "lyrics_timestamped": { "words": [ { "end": 0.64, "index_range": null, "line_index": 0, "start": 0.64, "text": "[Verse]", "wav2vec2_format": null }, ... }, { "end": 236.16, "index_range": null, "line_index": 29, "start": 225.28, "text": "high", "wav2vec2_format": null } ] }, "state": "succeeded", "style": "", "duration": 239.5299546485261 } ] }
curl -X POST 'https://api.acedata.cloud/riffusion/audios' \ -H 'accept: application/json' \ -H 'authorization: Bearer {token}' \ -H 'content-type: application/json' \ -d '{ "action": "extend", "model": "FUZZ-1.0 Pro", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_id": "b7376272-3902-49b4-a83b-62f7e6ab505c", "continue_at": 5 }'
{ "success": true, "task_id": "6388a0aa-b5ab-4485-baad-f0e0b7a7848c", "trace_id": "da143dbe-8263-45ac-b05a-1ed57dd4aa79", "data": [ { "id": "209e27e0-500c-44f3-9134-280690014920", "title": "City Rhythm", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/3a8378d5-94d4-49b7-9c0a-8432c0c4a39d/image/209e27e0-500c-44f3-9134-280690014920.jpg", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/3a8378d5-94d4-49b7-9c0a-8432c0c4a39d/audio/209e27e0-500c-44f3-9134-280690014920.m4a", "video_url": null, "created_at": "2025-06-23T02:00:53.473604Z", "model": null, "lyrics_timestamped": { "words": [ { "end": 4.48, "index_range": null, "line_index": 0, "start": 4.48, "text": "[Verse]", "wav2vec2_format": null }, ... { "end": 179.2, "index_range": null, "line_index": 29, "start": 178.56, "text": "high", "wav2vec2_format": null } ] }, "state": "succeeded", "style": "", "duration": 197.00850340136054 }, { "id": "ff50012e-ad1b-4b71-8d0e-6a633428a54f", "title": "Bright", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/3a8378d5-94d4-49b7-9c0a-8432c0c4a39d/image/ff50012e-ad1b-4b71-8d0e-6a633428a54f.jpg", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/3a8378d5-94d4-49b7-9c0a-8432c0c4a39d/audio/ff50012e-ad1b-4b71-8d0e-6a633428a54f.m4a", "video_url": null, "created_at": "2025-06-23T02:00:52.795796Z", "model": null, "lyrics_timestamped": { "words": [ { "end": 0.64, "index_range": null, "line_index": 0, "start": 0.64, "text": "[Verse]", "wav2vec2_format": null }, ... { "end": 186.88, "index_range": null, "line_index": 29, "start": 186.24, "text": "high", "wav2vec2_format": null } ] }, "state": "succeeded", "style": "", "duration": 213.85757369614512 } ] }
curl -X POST 'https://api.acedata.cloud/riffusion/audios' \ -H 'accept: application/json' \ -H 'authorization: Bearer {token}' \ -H 'content-type: application/json' \ -d '{ "action": "replace_section", "model": "FUZZ-1.0 Pro", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_id": "b7376272-3902-49b4-a83b-62f7e6ab505c", "replace_section_start": 3, "replace_section_end": 70 }'
{ "success": true, "task_id": "73defcbf-f876-4dd6-b60e-4c1c5ecd4565", "trace_id": "9f639389-7218-4cdb-ade9-b34228bb0f21", "data": [ { "id": "037f5e9d-9da4-4d79-b58f-1f433b40d54d", "title": "Sunrise Joy", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/881ad27f-39c1-4c31-a789-ecc822e13b8c/image/037f5e9d-9da4-4d79-b58f-1f433b40d54d.jpg", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/881ad27f-39c1-4c31-a789-ecc822e13b8c/audio/037f5e9d-9da4-4d79-b58f-1f433b40d54d.m4a", "video_url": null, "created_at": "2025-06-23T02:18:43.031184Z", "model": null, "lyrics_timestamped": { "words": [ { "end": 3.84, "index_range": null, "line_index": 0, "start": 3.84, "text": "[Verse]", "wav2vec2_format": null }, ... { "end": 159.36, "index_range": null, "line_index": 29, "start": 159.36, "text": "high", "wav2vec2_format": null } ] }, "state": "succeeded", "style": "", "duration": 199.2201133786848 }, { "id": "97638295-068f-4cbc-b076-66f522449bd5", "title": "Sunrise", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/881ad27f-39c1-4c31-a789-ecc822e13b8c/image/97638295-068f-4cbc-b076-66f522449bd5.jpg", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/881ad27f-39c1-4c31-a789-ecc822e13b8c/audio/97638295-068f-4cbc-b076-66f522449bd5.m4a", "video_url": null, "created_at": "2025-06-23T02:18:56.267775Z", "model": null, "lyrics_timestamped": { "words": [ { "end": 3.84, "index_range": null, "line_index": 0, "start": 3.84, "text": "[Verse]", "wav2vec2_format": null }, ... { "end": 159.36, "index_range": null, "line_index": 29, "start": 159.36, "text": "high", "wav2vec2_format": null } ] }, "state": "succeeded", "style": "", "duration": 199.2201133786848 } ] }
curl -X POST 'https://api.acedata.cloud/riffusion/audios' \ -H 'accept: application/json' \ -H 'authorization: Bearer {token}' \ -H 'content-type: application/json' \ -d '{ "action": "swap_sound", "model": "FUZZ-1.0 Pro", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_id": "b7376272-3902-49b4-a83b-62f7e6ab505c" }'
{ "success": true, "task_id": "93279260-5ca1-42d8-bde1-1fa62e0f5027", "trace_id": "bc4e28db-4897-4ffc-9e03-45f43da7a21c", "data": [ { "id": "242035c0-8ac2-4f0b-a19c-ac2fa49d4df3", "title": "Brightside", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/36494e8a-eb82-4d89-bbfa-ec719e19572b/image/242035c0-8ac2-4f0b-a19c-ac2fa49d4df3.jpg", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/36494e8a-eb82-4d89-bbfa-ec719e19572b/audio/242035c0-8ac2-4f0b-a19c-ac2fa49d4df3.m4a", "video_url": null, "created_at": "2025-06-23T02:02:32.799561Z", "model": null, "lyrics_timestamped": { "words": [ { "end": 1.28, "index_range": null, "line_index": 0, "start": 1.28, "text": "[Verse]", "wav2vec2_format": null }, ... { "end": 195.84, "index_range": null, "line_index": 29, "start": 195.84, "text": "high", "wav2vec2_format": null } ] }, "state": "succeeded", "style": "", "duration": 197.2696371882086 }, { "id": "594fe702-6c71-4b0c-abb6-21b58efc74a6", "title": "Sunrise", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/36494e8a-eb82-4d89-bbfa-ec719e19572b/image/594fe702-6c71-4b0c-abb6-21b58efc74a6.jpg", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/36494e8a-eb82-4d89-bbfa-ec719e19572b/audio/594fe702-6c71-4b0c-abb6-21b58efc74a6.m4a", "video_url": null, "created_at": "2025-06-23T02:02:30.523279Z", "model": null, "lyrics_timestamped": { "words": [ { "end": 0.64, "index_range": null, "line_index": 0, "start": 0.64, "text": "[Verse]", "wav2vec2_format": null }, ... { "end": 192.64, "index_range": null, "line_index": 29, "start": 192.64, "text": "high", "wav2vec2_format": null } ] }, "state": "succeeded", "style": "", "duration": 196.7198866213152 } ] }
curl -X POST 'https://api.acedata.cloud/riffusion/audios' \ -H 'accept: application/json' \ -H 'authorization: Bearer {token}' \ -H 'content-type: application/json' \ -d '{ "action": "swap_vocals", "model": "FUZZ-1.0 Pro", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_id": "b7376272-3902-49b4-a83b-62f7e6ab505c" }'
{ "success": true, "task_id": "a6e0d456-189b-4c78-9232-2fe72166ab39", "trace_id": "ee5769d4-ae94-4e5a-a85f-b3c0ddc2e48e", "data": [ { "id": "b8b1ed14-f43c-4738-a697-60ba24b6049d", "title": "Uplift", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/25ce4ddd-e48c-42e2-9ea3-8e03380508f2/image/b8b1ed14-f43c-4738-a697-60ba24b6049d.jpg", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/25ce4ddd-e48c-42e2-9ea3-8e03380508f2/audio/b8b1ed14-f43c-4738-a697-60ba24b6049d.m4a", "video_url": null, "created_at": "2025-06-23T02:04:18.477032Z", "model": null, "lyrics_timestamped": { "words": [ { "end": 2.56, "index_range": null, "line_index": 0, "start": 2.56, "text": "[Verse]", "wav2vec2_format": null }, ... { "end": 186.88, "index_range": null, "line_index": 29, "start": 171.52, "text": "high", "wav2vec2_format": null } ] }, "state": "succeeded", "style": "", "duration": 195.55968253968254 }, { "id": "dfd6eb9c-a1f3-4e1f-bbf9-e0b9625e459f", "title": "Vivid Rise", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/25ce4ddd-e48c-42e2-9ea3-8e03380508f2/image/dfd6eb9c-a1f3-4e1f-bbf9-e0b9625e459f.jpg", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/25ce4ddd-e48c-42e2-9ea3-8e03380508f2/audio/dfd6eb9c-a1f3-4e1f-bbf9-e0b9625e459f.m4a", "video_url": null, "created_at": "2025-06-23T02:04:27.140387Z", "model": null, "lyrics_timestamped": { "words": [ { "end": 1.28, "index_range": null, "line_index": 0, "start": 1.28, "text": "[Verse]", "wav2vec2_format": null }, ... { "end": 188.8, "index_range": null, "line_index": 29, "start": 188.16, "text": "high", "wav2vec2_format": null } ] }, "state": "succeeded", "style": "", "duration": 196.07185941043085 } ] }
異步回調
由于 Riffusion Audios Generation API 生成的時間有時候會相對較長,如果 API 長時間無響應,HTTP 請求會一直保持連接,導致額外的系統資源消耗,所以本 API 也提供了異步回調的支持。
整體流程是:客戶端發起請求的時候,額外指定一個 callback_url 字段,客戶端發起 API 請求之后,API 會立馬返回一個結果,包含一個 task_id 的字段信息,代表當前的任務 ID。當任務完成之后,生成任務的結果會通過 POST JSON 的形式發送到客戶端指定的 callback_url,其中也包括了 task_id 字段,這樣任務結果就可以通過 ID 關聯起來了。
{ "success": true, "task_id": "9939767a-7f9c-4f43-aabf-ca68fe385f3c", "trace_id": "13a86870-e705-45d0-8447-82a08701c0fa", "data": [ { "id": "72e6c476-0116-4da9-ae34-f78190020b35", "title": "Rise", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/9b9f3281-6b47-44ac-8e4b-3b0d105e163d/image/72e6c476-0116-4da9-ae34-f78190020b35.jpg", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/9b9f3281-6b47-44ac-8e4b-3b0d105e163d/audio/72e6c476-0116-4da9-ae34-f78190020b35.m4a", "video_url": null, "created_at": "2025-06-15T15:43:22.432605Z", "model": "FUZZ-1.0", "state": "succeeded", "style": "acoustic folk, finger picking", "duration": 184.96 }, { "id": "7f4f5c20-4395-4583-9dbb-735b9bb86957", "title": "Luminance", "image_url": "https://storage.googleapis.com/corpusant-app-public/riffs/9b9f3281-6b47-44ac-8e4b-3b0d105e163d/image/7f4f5c20-4395-4583-9dbb-735b9bb86957.jpg", "lyric": "[Verse]\nWoke up with the sun in my eyes\nNo clouds above just blue in the skies\nShoes on my feet I’m ready to run\nEvery step feels like a loaded gun\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Verse 2]\nDancing through the city streets\nA rhythm pounding in my heartbeat\nStrangers smile it’s catching on\nThis world’s a stage we’re all a song\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high\n[Bridge]\nThrow your worries out the door\nLet them sink to the ocean floor\nWe’re alive and it’s enough\nLife is messy but it’s love\n[Chorus]\nHappy days are rolling in\nLet the joy beneath my skin\nNo more shadows no more lies\nJust the truth that lifts me high", "audio_url": "https://storage.googleapis.com/corpusant-app-public/riffs/9b9f3281-6b47-44ac-8e4b-3b0d105e163d/audio/7f4f5c20-4395-4583-9dbb-735b9bb86957.m4a", "video_url": null, "created_at": "2025-06-15T15:43:21.574561Z", "model": "FUZZ-1.0", "state": "succeeded", "style": "deep bass, ethereal electronic", "duration": 165.12 } ] }
可以看到結果中有一個 task_id 字段,其他的字段都和上文類似,通過該字段即可實現任務的關聯。
錯誤處理
在調用 API 時,如果遇到錯誤,API 會返回相應的錯誤代碼和信息。例如:
400 token_mismatched:Bad request, possibly due to missing or invalid parameters.
400 api_not_implemented:Bad request, possibly due to missing or invalid parameters.
401 invalid_token:Unauthorized, invalid or missing authorization token.
429 too_many_requests:Too many requests, you have exceeded the rate limit.
500 api_error:Internal server error, something went wrong on the server.
我們還可以通過 position 參數控制二維碼的位置,比如說一張圖片里面有一個女生穿裙子,而我們想要把二維碼放在裙子的位置并與之融合起來,我們就可以嘗試改下二維碼的位置,調用樣例如下:
1 2 3 4 5 6 7 8 9 10
curl -X POST "https://api.zhishuyun.com/qrart/generate?token={token}" \ -H "accept: application/json" \ -H "content-type: application/json" \ -d '{ "type": "link", "content": "https://data.zhishuyun.com", "prompt": "one of the beautiful girls in the moonlight in the background, in the style of pixelated chaos, rococo-inspired art, dark white and sky-blue, made of plastic, delicate flowers, gongbi, wimmelbilder", "position": "bottom", "aspect_ratio": "576x1008" }'
Nexior 是 GitHub 上的一個開源項目,利用它我們可以一鍵部署自己的 AI 應用站點,包括 AI 問答、Midjourney 繪畫、知識庫問答、藝術二維碼等應用,無需自己開發 AI 系統、無需采購 AI 賬號、無需關心 API 支持、無需配置支付系統,零啟動成本,無風險通過 AI 賺取收益。
本文章會介紹 Nexior 項目在 Vercel 上的部署流程,無需任何編程技巧即可幾分鐘部署一套屬于自己的 AI 站點,并輕松利用該站點獲取收益。
{ "success": true, "data": [ { "id": "2f16f7bc-4135-42c6-b3c5-6d6c49dc8cd5", "title": "Winter Wonderland", "image_url": "https://cdn1.suno.ai/image_2f16f7bc-4135-42c6-b3c5-6d6c49dc8cd5.png", "lyric": "[Verse]\nSnowflakes falling all around\nGlistening white\nCovering the ground\nChildren laughing\nFull of delight\nIn this winter wonderland tonight\nSanta's sleigh\nUp in the sky\nRudolph's nose shining bright\nOh my\nHear the jingle bells\nRinging so clear\nBringing joy and holiday cheer\n[Verse 2]\nRoasting chestnuts by the fire's glow\nChristmas lights\nThey twinkle and show\nFamilies gathering with love and cheer\nSpreading warmth to everyone near", "audio_url": "https://cdn1.suno.ai/2f16f7bc-4135-42c6-b3c5-6d6c49dc8cd5.mp3", "video_url": "https://cdn1.suno.ai/2f16f7bc-4135-42c6-b3c5-6d6c49dc8cd5.mp4", "created_at": "2024-05-10T16:21:37.624Z", "model": "chirp-v3", "prompt": "A song for Christmas", "style": "holiday" }, { "id": "5dca232b-17cc-4896-a2d1-4b59178bf410", "title": "Winter Wonderland", "image_url": "https://cdn1.suno.ai/image_5dca232b-17cc-4896-a2d1-4b59178bf410.png", "lyric": "[Verse]\nSnowflakes falling all around\nGlistening white\nCovering the ground\nChildren laughing\nFull of delight\nIn this winter wonderland tonight\nSanta's sleigh\nUp in the sky\nRudolph's nose shining bright\nOh my\nHear the jingle bells\nRinging so clear\nBringing joy and holiday cheer\n[Verse 2]\nRoasting chestnuts by the fire's glow\nChristmas lights\nThey twinkle and show\nFamilies gathering with love and cheer\nSpreading warmth to everyone near", "audio_url": "https://cdn1.suno.ai/5dca232b-17cc-4896-a2d1-4b59178bf410.mp3", "video_url": "https://cdn1.suno.ai/5dca232b-17cc-4896-a2d1-4b59178bf410.mp4", "created_at": "2024-05-10T16:21:37.624Z", "model": "chirp-v3", "prompt": "A song for Christmas", "style": "holiday" } ] }
可以看到這時候我們就得到了兩首歌的內容,包括標題、預覽圖、歌詞、音頻、視頻等內容。
字段說明如下:
success:生成是否成功,如果成功則為 true,否則為 false
data:是一個列表,包含了生成的歌曲的詳細信息。
id:歌曲 ID
title:歌曲的標題
image_url:歌曲的封面圖片
lyric:歌曲的歌詞
audio_url:歌曲的音頻文件,打開就是一個 mp3 音頻。
video_url:歌曲的視頻文件,打開就是一個 mp4 視頻。
created_at:創建的時間
model:使用的模型,一般是最新的 v3 模型
style:風格
自定義生成
如果想自定義生成歌詞,可以輸入歌詞:
這時候 lyric 字段可以傳入類似如下內容:
1
[Verse]\nSnowflakes falling all around\nGlistening white\nCovering the ground\nChildren laughing\nFull of delight\nIn this winter wonderland tonight\nSanta's sleigh\nUp in the sky\nRudolph's nose shining bright\nOh my\nHear the jingle bells\nRinging so clear\nBringing joy and holiday cheer\n[Verse 2]\nRoasting chestnuts by the fire's glow\nChristmas lights\nThey twinkle and show\nFamilies gathering with love and cheer\nSpreading warmth to everyone near
注意,這里的歌詞中 \n 是換行符,如果你不知道如何生成歌詞,可以使用下文介紹的生成歌詞的 API 自助生成。
curl -X POST 'https://api.acedata.cloud/suno/audios' \ -H 'authorization: Bearer {token}' \ -H 'accept: application/json' \ -H 'content-type: application/json' \ -d '{ "lyric": "[Verse]\\nSnowflakes falling all around\\nGlistening white\\nCovering the ground\\nChildren laughing\\nFull of delight\\nIn this winter wonderland tonight\\nSanta's sleigh\\nUp in the sky\\nRudolph's nose shining bright\\nOh my\\nHear the jingle bells\\nRinging so clear\\nBringing joy and holiday cheer\\n[Verse 2]\\nRoasting chestnuts by the fire's glow\\nChristmas lights\\nThey twinkle and show\\nFamilies gathering with love and cheer\\nSpreading warmth to everyone near", "custom": true }'
測試允許,生成的效果是類似的。
異步回調
由于 Suno 生成音樂的時間相對較長,大約需要 1-2 分鐘,如果 API 長時間無響應,HTTP 請求會一直保持連接,導致額外的系統資源消耗,所以本 API 也提供了異步回調的支持。
整體流程是:客戶端發起請求的時候,額外指定一個 callback_url 字段,客戶端發起 API 請求之后,API 會立馬返回一個結果,包含一個 task_id 的字段信息,代表當前的任務 ID。當任務完成之后,生成音樂的結果會通過 POST JSON 的形式發送到客戶端指定的 callback_url,其中也包括了 task_id 字段,這樣任務結果就可以通過 ID 關聯起來了。
{ "success": true, "task_id": "44472ab8-783b-4054-b861-5bf14e462f60", "data": [ { "id": "da4324e5-84b2-484b-b0e9-dd261381c594", "title": "Winter Whispers", "image_url": "https://cdn1.suno.ai/image_da4324e5-84b2-484b-b0e9-dd261381c594.png", "lyric": "[Verse]\nSnow falling gently from the sky\nChildren giggling as they pass by\nFire crackling\nCozy and warm\nChristmas spirit begins to swarm\n[Verse 2]\nTwinkling lights\nA sight to behold\nStockings hung\nWaiting to be filled with gold\nGifts wrapped with love\nPiled high\nExcitement in the air\nYou can't deny\n[Chorus]\nWinter whispers in the wind\nJoy and love it brings\nLet's celebrate this season\nWith the ones we're missing", "audio_url": "https://cdn1.suno.ai/da4324e5-84b2-484b-b0e9-dd261381c594.mp3", "video_url": "https://cdn1.suno.ai/da4324e5-84b2-484b-b0e9-dd261381c594.mp4", "created_at": "2024-05-11T07:33:05.430Z", "model": "chirp-v3", "prompt": "A song for Christmas", "style": "pop" }, { "id": "b878a87b-a0db-4046-8ccd-ecd2fb3d4372", "title": "Winter Whispers", "image_url": "https://cdn1.suno.ai/image_b878a87b-a0db-4046-8ccd-ecd2fb3d4372.png", "lyric": "[Verse]\nSnow falling gently from the sky\nChildren giggling as they pass by\nFire crackling\nCozy and warm\nChristmas spirit begins to swarm\n[Verse 2]\nTwinkling lights\nA sight to behold\nStockings hung\nWaiting to be filled with gold\nGifts wrapped with love\nPiled high\nExcitement in the air\nYou can't deny\n[Chorus]\nWinter whispers in the wind\nJoy and love it brings\nLet's celebrate this season\nWith the ones we're missing", "audio_url": "https://cdn1.suno.ai/b878a87b-a0db-4046-8ccd-ecd2fb3d4372.mp3", "video_url": "https://cdn1.suno.ai/b878a87b-a0db-4046-8ccd-ecd2fb3d4372.mp4", "created_at": "2024-05-11T07:33:05.430Z", "model": "chirp-v3", "prompt": "A song for Christmas", "style": "pop" } ] }
{ "success": true, "task_id": "57e8ce3a-39cb-41a2-802f-e70a324f4d0a", "data": { "text": "[Verse]\nSnowflakes falling from the sky\nWinter's cold touch\nOh how it gets me high\nI bundle up in layers\nOh so cozy\nStepping out and feeling the frost on my nose\nSee\n\n[Verse 2]\nThe world is covered in a blanket of white\nIcicles hanging\nShimmering so bright\nThe chilly air fills my lungs with every breath\nWalking in the snow\nLeaving footprints that won't be left\n\n[Chorus]\nOh\nWinter's cold touch\nIt's a season that I love so much\nSnowfall brings a feeling so divine\nWinter's cold touch\nIt's a magical time", "title": "Winter's Cold Touch", "status": "complete" } }
{ "answer": "I am an AI language model developed by OpenAI and I don't have a personal name. However, you can call me GPT or simply Chatbot. How can I assist you today?" }
{ "answer": "I am an AI language model created by OpenAI and I don't have a personal name. You can simply call me OpenAI or ChatGPT. How can I assist you today?", "id": "7cdb293b-2267-4979-a1ec-48d9ad149916" }
第二次請求,將第一次請求返回的 id 字段作為參數傳遞,同時 stateful 參數依然設置為 true,詢問「What I asked you just now?」,如圖所示:
對應代碼如下:
1 2 3 4 5 6 7 8 9 10
curl -X POST 'https://api.acedata.cloud/aichat/conversations' \ -H 'accept: application/json' \ -H 'authorization: Bearer {token}' \ -H 'content-type: application/json' \ -d '{ "model": "gpt-3.5", "stateful": true, "id": "7cdb293b-2267-4979-a1ec-48d9ad149916", "question": "What I asked you just now?" }'
結果如下:
1 2 3 4
{ "answer": "You asked me what my name is. As an AI language model, I do not possess a personal identity, so I don't have a specific name. However, you can refer to me as OpenAI or ChatGPT, the names used for this AI model. Is there anything else I can help you with?", "id": "7cdb293b-2267-4979-a1ec-48d9ad149916" }
@Override publicvoidonResponse(Call call, Response response)throws IOException { if (!response.isSuccessful()) thrownew IOException("Unexpected code " + response); try (BufferedReader br = new BufferedReader( new InputStreamReader(response.body().byteStream(), "UTF-8"))) { String responseLine; while ((responseLine = br.readLine()) != null) { System.out.println(responseLine); } } } });
其他語言可以另外自行改寫,原理都是一樣的。
模型預設
我們知道,OpenAI 相關的 API 有對應的 system_prompt 的概念,就是給整個模型設置一個預設,比如它叫什么名字等等。本 AI 問答 API 也暴露了這個參數,叫做 preset,利用它我們可以給模型增加預設,我們用一個例子來體驗下:
這里我們額外添加 preset 字段,內容為 You are a professional artist,如圖所示:
對應代碼如下:
1 2 3 4 5 6 7 8 9 10
curl -X POST 'https://api.acedata.cloud/aichat/conversations' \ -H 'accept: application/json' \ -H 'authorization: Bearer {token}' \ -H 'content-type: application/json' \ -d '{ "model": "gpt-3.5", "stateful": true, "question": "What can you help me?", "preset": "You are a professional artist" }'
運行結果如下:
1 2 3
{ "answer": "As a professional artist, I can offer a range of services and assistance depending on your specific needs. Here are a few ways I can help you:\n\n1. Custom Artwork: If you have a specific vision or idea, I can create custom artwork for you. This can include paintings, drawings, digital art, or any other medium you prefer.\n\n2. Commissioned Pieces: If you have a specific subject or concept in mind, I can create commissioned art pieces tailored to your preferences. This could be for personal enjoyment or as a unique gift for someone special.\n\n3. Art Consultation: If you need guidance on art selection, interior design, or how to showcase and display art in your space, I can provide professional advice to help enhance your aesthetic sense and create a cohesive look." }
curl -X POST 'https://api.acedata.cloud/aichat/conversations' \ -H 'accept: application/json' \ -H 'authorization: Bearer {token}' \ -H 'content-type: application/json' \ -d '{ "model": "gpt-4-vision", "question": "How many apples in the picture?", "references": ["https://cdn.acedata.cloud/ht05g0.png"] }'
運行結果如下:
1 2 3
{ "answer": "There are 5 apples in the picture." }
可以看到,我們就成功得到了對應圖片的回答結果。
聯網問答
本 API 還支持聯網模型,包括 GPT-3.5、GPT-4 均能支持,在 API 背后有一個自動搜索互聯網并總結的過程,我們可以選擇模型為 gpt-3.5-browsing 來體驗下,如圖所示:
代碼如下:
1 2 3 4 5 6 7 8
curl -X POST 'https://api.acedata.cloud/aichat/conversations' \ -H 'accept: application/json' \ -H 'authorization: Bearer {token}' \ -H 'content-type: application/json' \ -d '{ "model": "gpt-3.5-browsing", "question": "What's the weather of New York today?" }'
運行結果如下:
1 2 3
{ "answer": "The weather in New York today is as follows:\n- Current Temperature: 16°C (60°F)\n- High: 16°C (60°F)\n- Low: 10°C (50°F)\n- Humidity: 47%\n- UV Index: 6 of 11\n- Sunrise: 5:42 am\n- Sunset: 8:02 pm\n\nIt's overcast with a chance of occasional showers overnight, and the chance of rain is 50%.\nFor more details, you can visit [The Weather Channel](https://weather.com/weather/tenday/l/96f2f84af9a5f5d452eb0574d4e4d8a840c71b05e22264ebdc0056433a642c84).\n\nIs there anything else you'd like to know?" }
可以看到,這里它自動聯網搜索了 The Weather Channel 網站,并獲得了里面的信息,然后進一步返回了實時結果。
在這個數字化時代,人工智能技術正以驚人的速度改變著我們的生活方式和創造方式。音樂作為一種最直接、最感性的藝術形式,自然也成為了人工智能技術的應用場景之一。今天,我們將以 Vue 和 Node.js 為基礎,利用現有的 API 來快速搭建一個 Suno AI 音樂站點。讓我們一起探索這個令人興奮的過程吧!
<template> <divid="app"> <header> <h1>XiaoZhi AI Music Generator</h1> </header> <main> <divclass="input-container"> <inputtype="text"v-model="musicTitle"placeholder="Enter a prompt for the music"> <button @click="handleGenerateMusic":disabled="loading">生成音樂</button> </div> <divv-if="loading"class="loading"> Music is being generated for you, please wait... </div>
<divv-if="musicGenerated"class="music-container"> <divv-for="music in generatedMusic":key="music.id"class="music-item"> <h2>{{ music.title }}</h2> <img:src="music.image_url"alt="Music Image"> <pclass="lyric">{{ music.lyric }}</p> <audiocontrolsclass="audio" @play="stopOtherMedia($event)"> <source:src="music.audio_url"type="audio/mpeg"> Your browser does not support the audio element. </audio> <videocontrolsclass="video" @play="stopOtherMedia($event)"> <source:src="music.video_url"type="video/mp4"> Your browser does not support the video element. </video> </div> </div>
我們還可以通過 position 參數控制二維碼的位置,比如說一張圖片里面有一個女生穿裙子,而我們想要把二維碼放在裙子的位置并與之融合起來,我們就可以嘗試改下二維碼的位置,調用樣例如下:
1 2 3 4 5 6 7 8 9
curl -X POST "https://api.zhishuyun.com/qrart/generate?token={token}" \ -H "accept: application/json" \ -H "content-type: application/json" \ -d '{ "type": "link", "content": "https://data.zhishuyun.com", "prompt": "one of the beautiful girls in the moonlight in the background, in the style of pixelated chaos, rococo-inspired art, dark white and sky-blue, made of plastic, delicate flowers, gongbi, wimmelbilder", "position": "bottom" }'
在這里我們就不再對各種 API 參數進行一一介紹了,更詳細更實時的內容可以參見知數云的官方文檔,鏈接為:https://data.zhishuyun.com/documents/ee085d2a-a0b9-4f0e-8b4d-8da407345138。
價格
知數云藝術二維碼的 API 提供了階梯定價,首次申請免費贈送 20 次,而且購買越多越便宜,由于價格會動態調整,所以大家可以查看知數云官網來查看最新實時價格:https://data.zhishuyun.com/services/38ecf158-36f2-42f2-8e7f-6786cdfc2452
價格怎么樣呢?由于價格可能會動態變化,大家可以直接參考知數云的官方網站了解:https://data.zhishuyun.com/services/d87e5e99-b797-4ade-9e73-b896896b0461。但總的來說,能夠以這個價格做到知數云 Midjourney API 這樣的穩定性和并發的,業界寥寥無幾,歡迎選購和評測。
這家代理的官方網站是 http://www.ipidea.net/?utm-source=cqc&utm-keyword=?ipidea。從他們的介紹可以看到,他們是一家全球范圍的 IP 代理服務商,能覆蓋全球 220 個國家和地區,大部分代理實際上是住宅 IP。
官方介紹這家的代理 IP 數量大約是九千萬左右,這個數量非常龐大,同時官方介紹說代理的可用率是 99.9%。
下面我們來看一下他們的一些套餐類型:
動態住宅代理:這種代理實際上就是用真實的住宅用戶的 IP 搭建的代理。一般來說,住宅代理對于很多場景的使用封禁概率會比較低,因為很多廠商對封禁住宅代理是比較謹慎的。動態住宅代理其實就是可以定時切換的 IP,比如說做網絡爬蟲,我們就需要不斷變換的不同的代理 IP,這樣可以進一步的減少被封禁的概率。
靜態住宅代理:相對于動態代理來說,靜態住宅代理的特點就是長效穩定,可以一直獲取一個穩定不變的代理 IP,適合長久的穩定的海外網絡環境使用。比如說,我們要進行自動化網站的爬取,如果在一個頁面內 IP 地址頻繁變動會增大被風控的概率。所以,如果有一個長效穩定的住宅 IP 代理,就會非常方便。
數據中心代理:這種代理實際上是很多服務器廠商的服務器搭建起來的代理。例如騰訊云、阿里云、微軟云等服務器所在的 IP 地址段,就屬于所謂的數據中心的 IP 地址段。因此,用這些服務器搭建出來的代理就叫做數據中心代理。一般來說,這種數據中心代理相對于住宅代理更容易被爬蟲封禁,但是這種代理的優勢就是價格更加便宜,而且網絡速度也會相對較好。
I want you to act as a javascript console. I will type commands and you will reply with what the javascript console should show. I want you to only reply with the terminal output inside one unique code block, and nothing else. do not write explanations. do not type commands unless I instruct you to do so. when i need to tell you something in english, i will do so by putting text inside curly brackets {like this}. my first command is console.log(“Hello World”);
import time from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.remote.webelement import WebElement from selenium.webdriver.common.action_chains import ActionChains from app.captcha_resolver import CaptchaResolver
# click captchas recognized_indices = [i for i, x in enumerate(recognized_results) if x] logger.debug(f'recognized_indices {recognized_indices}') click_targets = self.wait.until(EC.visibility_of_all_elements_located( (By.CSS_SELECTOR, '.task-image'))) for recognized_index in recognized_indices: click_target: WebElement = click_targets[recognized_index] click_target.click() time.sleep(random())
當然我們也可以通過執行 JavaScript 來對每個節點進行模擬點擊,效果是類似的。
這里我們用 for 循環將 true false 列表轉成了一個列表,列表的每個元素代表 true 在列表中的位置,其實就是我們的點擊目標了。
然后接著我們獲取了所有的驗證碼小圖對應的節點,然后依次調用 click 方法進行點擊即可。
這樣我們就可以實現驗證碼小圖的逐個識別了。
點擊驗證
好,那么有了上面的邏輯,我們就能完成整個 HCaptcha 的識別和點選了。
最后,我們模擬點擊驗證按鈕就好了:
1 2 3 4 5
# after all captcha clicked verify_button: WebElement = self.get_verify_button() if verify_button.is_displayed: verify_button.click() time.sleep(3)
import time from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.remote.webelement import WebElement from selenium.webdriver.common.action_chains import ActionChains from app.captcha_resolver import CaptchaResolver
defget_question_id_by_target_name(target_name): logger.debug(f'try to get question id by {target_name}') question_id = CAPTCHA_TARGET_NAME_QUESTION_ID_MAPPING.get(target_name) logger.debug(f'question_id {question_id}') return question_id
single_captcha_elements = self.wait.until(EC.visibility_of_all_elements_located( (By.CSS_SELECTOR, '#rc-imageselect-target table td'))) for recognized_index in recognized_indices: single_captcha_element: WebElement = single_captcha_elements[recognized_index] single_captcha_element.click() # check if need verify single captcha self.verify_single_captcha(recognized_index)
defverify_single_captcha(self, index): time.sleep(3) elements = self.wait.until(EC.visibility_of_all_elements_located( (By.CSS_SELECTOR, '#rc-imageselect-target table td'))) single_captcha_element: WebElement = elements[index] class_name = single_captcha_element.get_attribute('class') logger.debug(f'verifiying single captcha {index}, class {class_name}') if'selected'in class_name: logger.debug(f'no new single captcha displayed') return logger.debug('new single captcha displayed') single_captcha_url = single_captcha_element.find_element_by_css_selector( 'img').get_attribute('src') logger.debug(f'single_captcha_url {single_captcha_url}') with open(CAPTCHA_SINGLE_IMAGE_FILE_PATH, 'wb') as f: f.write(requests.get(single_captcha_url).content) resized_single_captcha_base64_string = resize_base64_image( CAPTCHA_SINGLE_IMAGE_FILE_PATH, (100, 100)) single_captcha_recognize_result = self.captcha_resolver.create_task( resized_single_captcha_base64_string, get_question_id_by_target_name(self.captcha_target_name)) ifnot single_captcha_recognize_result: logger.error('count not get single captcha recognize result') return has_object = single_captcha_recognize_result.get( 'solution', {}).get('hasObject') if has_object isNone: logger.error('count not get captcha recognized indices') return if has_object isFalse: logger.debug('no more object in this single captcha') return if has_object: single_captcha_element.click() # check for new single captcha self.verify_single_captcha(index)
OK,這里我們定義了一個 verify_single_captcha 方法,然后傳入了格子對應的序號。接著我們首先嘗試查找格子對應的節點,然后找出對應的 HTML 的 class 屬性。如果沒有出現新的小圖,那就是這樣的選中狀態,對應的 class 就包含了 selected 字樣,如圖所示:
比如說,我們有兩臺主機 A、B,我們最終想實現在 A 上控制 B。那么如果用正向 Shell,其實就是在 A 上輸入 B 的連接地址,比如通過 ssh 連接到 B,連接成功之后,我們就可以在 A 上通過命令控制 B 了。如果用反向 Shell,那就是在 A 上先開啟一個監聽端口,然后讓 B 去連接 A 的這個端口,連接成功之后,A 這邊就能通過命令控制 B 了。
反彈 Shell 有什么用?
還是原來的例子,我們想用 A 來控制 B,如果想用 ssh 等命令來控制,那得輸入 B 的 sshd 地址或者端口對吧?但是在很多情況下,由于防火墻、安全組、局域網、NAT 等原因,我們實際上是無法直接連接到 B 的,比如:
網頁是運行在瀏覽器端的,當我們瀏覽一個網頁時,其 HTML 代碼、 JavaScript 代碼都會被下載到瀏覽器中執行。借助瀏覽器的開發者工具,我們可以看到網頁在加載過程中所有網絡請求的詳細信息,也能清楚地看到網站運行的 HTML 代碼和 JavaScript 代碼,這些代碼中就包含了網站加載的全部邏輯,如加載哪些資源、請求接口是如何構造的、頁面是如何渲染的等等。正因為代碼是完全透明的,所以如果我們能夠把其中的執行邏輯研究出來,就可以模擬各個網絡請求進行數據爬取了。
網站運營者首先想到防護措施可能是對某些數據接口的參數進行加密,比如說對某些 URL 的一些參數加上校驗碼或者把一些 id 信息進行編碼,使其變得難以閱讀或構造;或者對某些 API 請求加上一些 token、sign 等簽名,這樣這些請求發送到服務器時,服務器會通過客戶端發來的一些請求信息以及雙方約定好的秘鑰等來對當前的請求進行校驗,如果校驗通過,才返回對應數據結果。
var a = ["hello"]; (function (c, d) { var e = function (f) { while (--f) { c["push"](c["shift"]()); } }; e(++d); })(a, 0x9b); var b = function (c, d) { c = c - 0x0; var e = a[c]; return e; }; let hello = "1" + 0x1; console["log"](b("0x0"), hello);
在一些付費代理套餐中,大家可能會注意到有這樣的一個套餐 - 獨享代理或私密代理,這種其實就是用了專用服務器搭建了代理服務,相對一般的付費代理來說,其穩定性更好,速度也更快,同時 IP 可以動態變化。這種獨享代理或私密代理的 IP 切換大多數都是基于 ADSL 撥號機制來實現的,一臺云主機每撥號一次就可以換一個 IP,同時云主機上搭建了代理服務,我們就可以直接使用該云主機的 HTTP 代理來進行數據爬取了。
本節我們就來實際操作一下搭建 ADSL 撥號代理服務的方法。
1. 什么是 ADSL
ADSL,英文全稱是 Asymmetric Digital Subscriber Line,即非對稱數字用戶環路。它的上行和下行帶寬不對稱,它采用頻分復用技術把普通的電話線分成了電話、上行和下行 3 個相對獨立的信道,從而避免了相互之間的干擾。
ADSL 通過撥號的方式上網,撥號時需要輸入 ADSL 賬號和密碼,每次撥號就更換一個 IP。IP 分布在多個 A 段,如果 IP 都能使用,則意味著 IP 量級可達千萬。如果我們將 ADSL 主機作為代理,每隔一段時間云主機撥號就換一個 IP,這樣可以有效防止 IP 被封禁。另外,由于我們是直接使用專有的云主機搭建的代理服務,所以其代理的穩定性相對更好,代理響應速度也相對更快。
接口模塊:需要用 API 來提供對外服務的接口。其實我們可以直接連接數據庫來取對應的數據,但是這樣就需要知道數據庫的連接信息,并且要配置連接,而比較安全和方便的方式就是提供一個 Web API 接口,我們通過訪問接口即可拿到可用代理。另外,由于可用代理可能有多個,所以我們可以設置一個隨機返回某個可用代理的接口,這樣就能保證每個可用代理都可以取到,實現負載均衡。
import redis from proxypool.exceptions import PoolEmptyException from proxypool.schemas.proxy import Proxy from proxypool.setting import REDIS_HOST, REDIS_PORT, REDIS_PASSWORD, REDIS_KEY, PROXY_SCORE_MAX, PROXY_SCORE_MIN, \ PROXY_SCORE_INIT from random import choice from typing import List from loguru import logger from proxypool.utils.proxy import is_valid_proxy, convert_proxy_or_proxies
defadd(self, proxy: Proxy, score=PROXY_SCORE_INIT) -> int: """ add proxy and set it to init score :param proxy: proxy, ip:port, like 8.8.8.8:88 :param score: int score :return: result """ ifnot is_valid_proxy(f'{proxy.host}:{proxy.port}'): logger.info(f'invalid proxy {proxy}, throw it') return ifnot self.exists(proxy): if IS_REDIS_VERSION_2: return self.db.zadd(REDIS_KEY, score, proxy.string()) return self.db.zadd(REDIS_KEY, {proxy.string(): score})
defrandom(self) -> Proxy: """ get random proxy firstly try to get proxy with max score if not exists, try to get proxy by rank if not exists, raise error :return: proxy, like 8.8.8.8:8 """ # try to get proxy with max score proxies = self.db.zrangebyscore(REDIS_KEY, PROXY_SCORE_MAX, PROXY_SCORE_MAX) if len(proxies): return convert_proxy_or_proxies(choice(proxies)) # else get proxy by rank proxies = self.db.zrevrange(REDIS_KEY, PROXY_SCORE_MIN, PROXY_SCORE_MAX) if len(proxies): return convert_proxy_or_proxies(choice(proxies)) # else raise error raise PoolEmptyException
defdecrease(self, proxy: Proxy) -> int: """ decrease score of proxy, if small than PROXY_SCORE_MIN, delete it :param proxy: proxy :return: new score """ score = self.db.zscore(REDIS_KEY, proxy.string()) # current score is larger than PROXY_SCORE_MIN if score and score > PROXY_SCORE_MIN: logger.info(f'{proxy.string()} current score {score}, decrease 1') if IS_REDIS_VERSION_2: return self.db.zincrby(REDIS_KEY, proxy.string(), -1) return self.db.zincrby(REDIS_KEY, -1, proxy.string()) # otherwise delete proxy else: logger.info(f'{proxy.string()} current score {score}, remove') return self.db.zrem(REDIS_KEY, proxy.string())
defmax(self, proxy: Proxy) -> int: """ set proxy to max score :param proxy: proxy :return: new score """ logger.info(f'{proxy.string()} is valid, set to {PROXY_SCORE_MAX}') if IS_REDIS_VERSION_2: return self.db.zadd(REDIS_KEY, PROXY_SCORE_MAX, proxy.string()) return self.db.zadd(REDIS_KEY, {proxy.string(): PROXY_SCORE_MAX})
defcount(self) -> int: """ get count of proxies :return: count, int """ return self.db.zcard(REDIS_KEY)
defall(self) -> List[Proxy]: """ get all proxies :return: list of proxies """ return convert_proxy_or_proxies(self.db.zrangebyscore(REDIS_KEY, PROXY_SCORE_MIN, PROXY_SCORE_MAX))
defbatch(self, start, end) -> List[Proxy]: """ get batch of proxies :param start: start index :param end: end index :return: list of proxies """ return convert_proxy_or_proxies(self.db.zrevrange(REDIS_KEY, start, end - 1))
if __name__ == '__main__': conn = RedisClient() result = conn.random() print(result)
from retrying import retry import requests from loguru import logger
classBaseCrawler(object): urls = []
@retry(stop_max_attempt_number=3, retry_on_result=lambda x: x is None) deffetch(self, url, **kwargs): try: response = requests.get(url, **kwargs) if response.status_code == 200: return response.text except requests.ConnectionError: return
@logger.catch defcrawl(self): """ crawl main method """ for url in self.urls: logger.info(f'fetching {url}') html = self.fetch(url) for proxy in self.parse(html): logger.info(f'fetched proxy {proxy.string()} from {url}') yield proxy
import pkgutil from .base import BaseCrawler import inspect
# load classes subclass of BaseCrawler classes = [] for loader, name, is_pkg in pkgutil.walk_packages(__path__): module = loader.find_module(name).load_module(name) for name, value in inspect.getmembers(module): globals()[name] = value if inspect.isclass(value) and issubclass(value, BaseCrawler) and value isnot BaseCrawler: classes.append(value) __all__ = __ALL__ = classes
asyncdeftest(self, proxy: Proxy): """ test single proxy :param proxy: Proxy object :return: """ asyncwith aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False)) as session: try: logger.debug(f'testing {proxy.string()}') asyncwith session.get(TEST_URL, proxy=f'http://{proxy.string()}', timeout=TEST_TIMEOUT, allow_redirects=False) as response: if response.status in TEST_VALID_STATUS: self.redis.max(proxy) logger.debug(f'proxy {proxy.string()} is valid, set max score') else: self.redis.decrease(proxy) logger.debug(f'proxy {proxy.string()} is invalid, decrease score') except EXCEPTIONS: self.redis.decrease(proxy) logger.debug(f'proxy {proxy.string()} is invalid, decrease score')
@logger.catch defrun(self): """ test main method :return: """ # event loop of aiohttp logger.info('stating tester...') count = self.redis.count() logger.debug(f'{count} proxies to test') for i in range(0, count, TEST_BATCH): # start end end offset start, end = i, min(i + TEST_BATCH, count) logger.debug(f'testing proxies from {start} to {end} indices') proxies = self.redis.batch(start, end) tasks = [self.test(proxy) for proxy in proxies] # run tasks using event loop self.loop.run_until_complete(asyncio.wait(tasks))
if __name__ == '__main__': tester = Tester() tester.run()
這里定義了一個類 Tester,__init__ 方法中建立了一個 RedisClient 對象,供該對象中其他方法使用。接下來,定義了一個 test 方法,這個方法用來檢測單個代理的可用情況,其參數就是被檢測的代理。注意,test 方法前面加了 async 關鍵詞,這代表這個方法是異步的。方法內部首先創建了 aiohttp 的 ClientSession 對象,可以直接調用該對象的 get 方法來訪問頁面。
測試鏈接在這里定義為常量 TEST_URL。如果針對某個網站有抓取需求,建議將 TEST_URL 設置為目標網站的地址,因為在抓取過程中,代理本身可能是可用的,但是該代理的 IP 已經被目標網站封掉了。例如,某些代理可以正常訪問百度等頁面,但是對知乎來說可能就被封了,所以我們可以將 TEST_URL 設置為知乎的某個頁面的鏈接。當請求失敗、代理被封時,分數自然會減下來,失效的代理就不會被取到了。
如果想做一個通用的代理池,則不需要專門設置 TEST_URL,既可以將其設置為一個不會封 IP 的網站,也可以設置為百度這類響應穩定的網站。
defrun_server(self): """ run server for api """ ifnot ENABLE_SERVER: logger.info('server not enabled, exit') return app.run(host=API_HOST, port=API_PORT, threaded=API_THREADED)
defrun(self): global tester_process, getter_process, server_process try: logger.info('starting proxypool...') if ENABLE_TESTER: tester_process = multiprocessing.Process(target=self.run_tester) logger.info(f'starting tester, pid {tester_process.pid}...') tester_process.start()
if ENABLE_GETTER: getter_process = multiprocessing.Process(target=self.run_getter) logger.info(f'starting getter, pid{getter_process.pid}...') getter_process.start()
if ENABLE_SERVER: server_process = multiprocessing.Process(target=self.run_server) logger.info(f'starting server, pid{server_process.pid}...') server_process.start()
tester_process.join() getter_process.join() server_process.join() except KeyboardInterrupt: logger.info('received keyboard interrupt signal') tester_process.terminate() getter_process.terminate() server_process.terminate() finally: # must call join method before calling is_alive tester_process.join() getter_process.join() server_process.join() logger.info(f'tester is {"alive"if tester_process.is_alive() else"dead"}') logger.info(f'getter is {"alive"if getter_process.is_alive() else"dead"}') logger.info(f'server is {"alive"if server_process.is_alive() else"dead"}') logger.info('proxy terminated')
if __name__ == '__main__': scheduler = Scheduler() scheduler.run()
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import WebDriverException import time from loguru import logger
COUNT = 1000
for i in range(1, COUNT + 1): try: browser = webdriver.Chrome() wait = WebDriverWait(browser, 10) browser.get('https://captcha1.scrape.center/') button = wait.until(EC.element_to_be_clickable( (By.CSS_SELECTOR, '.el-button'))) button.click() captcha = wait.until( EC.presence_of_element_located((By.CSS_SELECTOR, '.geetest_slicebg.geetest_absolute'))) time.sleep(5) captcha.screenshot(f'data/captcha/images/captcha_{i}.png') except WebDriverException as e: logger.error(f'webdriver error occurred {e.msg}') finally: browser.close()
我們在做爬蟲的過程中經常會遇到這樣的情況,最初爬蟲正常運行,正常抓取數據,一切看起來都是那么美好,然而一杯茶的功夫可能就會出現錯誤,比如 403 Forbidden,這時打開網頁一看,可能會看到 “您的 IP 訪問頻率太高” 這樣的提示。出現這種現象的原因是網站采取了一些反爬蟲措施。比如,服務器會檢測某個 IP 在單位時間內的請求次數,如果超過了這個閾值,就會直接拒絕服務,返回一些錯誤信息,這種情況可以稱為封 IP。
既然服務器檢測的是某個 IP 單位時間的請求次數,那么借助某種方式來偽裝我們的 IP,讓服務器識別不出是由我們本機發起的請求,不就可以成功防止封 IP 了嗎?
一種有效的方式就是使用代理,后面會詳細說明代理的用法。在這之前,需要先了解下代理的基本原理,它是怎樣實現偽裝 IP 的呢?
1. 基本原理
代理實際上指的就是代理服務器,英文叫作 Proxy Server,它的功能是代理網絡用戶去取得網絡信息。形象地說,它是網絡信息的中轉站。在我們正常請求一個網站時,是發送了請求給 Web 服務器,Web 服務器把響應傳回給我們。如果設置了代理服務器,實際上就是在本機和服務器之間搭建了一個橋,此時本機不是直接向 Web 服務器發起請求,而是向代理服務器發出請求,請求會發送給代理服務器,然后由代理服務器再發送給 Web 服務器,接著由代理服務器再把 Web 服務器返回的響應轉發給本機。這樣我們同樣可以正常訪問網頁,但這個過程中 Web 服務器識別出的真實 IP 就不再是我們本機的 IP 了,就成功實現了 IP 偽裝,這就是代理的基本原理。